package handler

import (
	"net/http"
	"strconv"

	example "git.oschina.net/wkc/master-key-go/proto/example"
	"github.com/emicklei/go-restful"
	"github.com/gorilla/websocket"
	"github.com/micro/go-micro/errors"
	qrcode "github.com/skip2/go-qrcode"
	"golang.org/x/net/context"
	"qiniupkg.com/x/log.v7"
)

const NAME = "go.micro.web.master-key-go"

var Client example.KeyMqClient

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
}

func Listen(w http.ResponseWriter, r *http.Request) {
	var (
		err error
		in  example.ListenRequest
	)
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println(err)
		return
	}
	defer conn.Close()

	if err := conn.ReadJSON(&in); err != nil {
		log.Error(err)
		return
	}
	ctx := context.Background()
	stream, err := Client.Listen(ctx, &in)
	if err != nil {
		log.Error(err)
		return
	}
	defer stream.Close()
	for {
		resp, err := stream.Recv()
		if err != nil {
			log.Error(err)
			return
		}
		err = conn.WriteJSON(resp)
		if err != nil {
			log.Error(err)
			return
		}
	}
}

func Version(req *restful.Request, rsp *restful.Response) {
	version := req.QueryParameter("version")
	ctx := context.Background()
	resp, err := Client.Version(ctx, &example.VersionRequest{Version: version})
	if err != nil {
		writeRpcError(rsp, err)
		return
	}
	rsp.WriteEntity(resp)
}

func Send(req *restful.Request, rsp *restful.Response) {
	in := example.SendRequest{}
	err := req.ReadEntity(&in)
	if err != nil {
		rsp.WriteError(http.StatusBadRequest, err)
		return
	}
	ctx := context.Background()
	resp, err := Client.Send(ctx, &in)
	if err != nil {
		writeRpcError(rsp, err)
		return
	}
	rsp.WriteEntity(resp)
}

func writeRpcError(rsp *restful.Response, err error) {
	rsp.AddHeader(restful.HEADER_ContentType, restful.MIME_JSON)
	rsp.WriteError(errCode(err), err)
}

func errCode(err error) (code int) {
	switch err2 := err.(type) {
	case *errors.Error:
		return int(err2.Code)
	}
	code = int(errors.Parse(err.Error()).Code)
	if code == 0 {
		code = http.StatusInternalServerError
	}
	return code
}

func QrCode(req *restful.Request, rsp *restful.Response) {
	url := req.QueryParameter("url")
	png, err := qrcode.Encode(url, qrcode.Medium, 256)
	if err != nil {
		writeRpcError(rsp, errors.BadRequest(NAME, err.Error()))
		return
	}
	rsp.AddHeader(restful.HEADER_ContentType, "image/png")
	rsp.AddHeader("Content-Length", strconv.Itoa(len(png)))
	rsp.Write(png)
}
